/**
 * Created by admin on 2016/6/25.
 */
var url = require('url');
var crypto = require('crypto');
var request = require('request');
var async = require('async');
var Q = require('q');
var _ = require('underscore');

var redis = require('redis'),
    RDS_PORT = 0,		//端口号
    RDS_HOST = '',	//服务器IP
    RDS_AUTH={};
var cache = {};
var wx_config = {};
var wxtoken = {};
function getToken(prefix,cb) {
    var tokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appId=' + wx_config[prefix].app_id + '&secret=' + wx_config[prefix].app_secret;
    request.get(tokenUrl, function(error, response, body) {
        if (error) {
            cb("getToken error", error);
        }
        else {
            try {
                var token = JSON.parse(body).access_token;
                cb(null, token);
            }
            catch (e) {
                cb("getToken error", e);
            }
        }
    });
}
function getNewTicket(token, cb) {
    request.get('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + token + '&type=jsapi', function(error, res, body) {
        if (error) {
            cb('getNewTicket error', error);
        }
        else {
            try {
                var ticket = JSON.parse(body).ticket;
                cb(null, ticket);
            }
            catch (e) {
                cb('getNewTicket error', e);
            }
        }
    });
}
function tryGetSignature(prefix,u, cb) {
    var now = Math.floor(_.now()/1000);
    // 判断cache 是否过期
    if (!cache[prefix] || !cache[prefix].ticket || (now - cache[prefix].time) > 7000) {
        cache[prefix].time = cache[prefix].time + 10 * 1000;  // 缓解高并发多次获取
        async.waterfall([
            function(cb) {
                getAccessToken(prefix,cb);
            },
            function(result, cb) {
                getNewTicket(result[prefix].token, cb);
            }], function(error, result) {
            if (error) {
                cb('getToken getNewTicket error', error);
            }
            else {
                cache[prefix] = {
                    ticket:result,
                    time:now
                };
                // 文件保存
                var client = redis.createClient(RDS_PORT,RDS_HOST,RDS_AUTH);
                client.set(prefix +"jsapi_ticket",'{"jsapi_ticket":"'+result+'","expire_time":'+(+now+7000)+'}',redis.print);
                client.quit();//必须关闭

                var timestamp = getTimesTamp();
                var noncestr = getNonceStr();
                var str = prefix +"jsapi_ticket" + result + '&noncestr='+ noncestr+'&timestamp=' + timestamp + '&url=' + u;
                var signature = crypto.createHash('sha1').update(str).digest('hex');
                cb(null, {
                    appId: wx_config[prefix].app_id,
                    timestamp: timestamp,
                    nonceStr: noncestr,
                    signature: signature
                });
            }
        });
    }
    else {
        var timestamp = getTimesTamp();
        var noncestr = getNonceStr();
        var str = 'jsapi_ticket=' + cache[prefix].ticket + '&noncestr=' + noncestr + '&timestamp=' + timestamp + '&url=' + u;
        var signature = crypto.createHash('sha1').update(str).digest('hex');
        cb(null, {
            appId: wx_config[prefix].app_id,
            timestamp: timestamp,
            nonceStr: noncestr,
            signature: signature
        });
    }
}
function getTimesTamp() {
    return parseInt(new Date().getTime() / 1000) + '';
}

function getNonceStr() {
    return Math.random().toString(36).substr(2, 15);
}
function getSignature(prefix,url, cb) {
    // 判断内存中是否有缓存
    var now = Math.floor(_.now()/1000);
    if (!cache[prefix] || !cache[prefix].ticket || (now - wxtoken[prefix].time) > 7000) {
        var client = redis.createClient(RDS_PORT,RDS_HOST,RDS_AUTH);
        client.get(prefix +"jsapi_ticket", function (err, keys) {
            var wx_keys = JSON.parse(keys);
            if(_.has(wx_keys, 'jsapi_ticket')){
                cache[prefix] = {
                    ticket:wx_keys.jsapi_ticket,
                    time:wx_keys.expire_time  //10位时间戳
                };
            }
            client.quit();//必须关闭
            tryGetSignature( prefix,url, cb);
        });
    }
    else {
        tryGetSignature( prefix,url, cb);
    }
}

//尝试获取TOKEN
function tryGetToken(prefix,cb){
    var now = Math.floor(_.now()/1000);
    if (!wxtoken[prefix]||!wxtoken[prefix].token || (now - wxtoken[prefix].time) > 7000) {
        //wxtoken.time = wxtoken.time + 10;  // 缓解高并发多次获取
        async.waterfall([
            function(cb) {
                getToken(prefix, cb);
            }], function(error, result) {
            if (error) {
                cb(error, error);
            }
            else {
                wxtoken[prefix] = {
                    token:result,
                    time:now+7000
                };
                // 文件保存
                var client = redis.createClient(RDS_PORT,RDS_HOST,RDS_AUTH);
                client.set(prefix +"access_token",'{"access_token":"'+result+'","expire_time":'+(+now+7000)+'}',redis.print);
                client.quit();//必须关闭
                cb(null, wxtoken);
            }
        });
    }else{
        cb(null,wxtoken);
    }
}
function getAccessToken(prefix,cb) {
    // 判断内存中是否有缓存
    var now = Math.floor(_.now()/1000);
    if (!wxtoken||!wxtoken[prefix] || !wxtoken[prefix].token || (now - wxtoken[prefix].time) > 7000) {
        var client = redis.createClient(RDS_PORT,RDS_HOST,RDS_AUTH);
        client.get(prefix+"access_token", function (err, keys) {
            var wx_keys = JSON.parse(keys);
            if(_.has(wx_keys,"access_token")){
                wxtoken[prefix] = {
                    token:wx_keys.access_token,
                    time:wx_keys.expire_time //10位时间戳
                }
            }
            client.quit();//必须关闭
            tryGetToken(prefix, cb);
        });
    }else{
        tryGetToken(prefix,cb);
    }
}

//-----------获取关注用户基本信息（包括UnionID机制）------------
function getUserInfo(prefix,access_token,openid,cb){
    var userinfoUrl = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='+access_token+'&openid='+openid+'&lang=zh_CN';
    var now = Math.floor(_.now()/1000);
    request.get(userinfoUrl, function(error, response, body) {
        if (error) {
            cb('getUserinfoUrl error', error);
        }
        else {
            try {
                var Userinfo = JSON.parse(body);
                //console.log(Userinfo); //有时候USERINFO会得不到 因为在有效期内token可能损坏
                if(Userinfo.errcode===40001 || Userinfo.errcode===42001){ //如果发现Token无效 需要重新获取一次token
                    async.waterfall([
                        function(cb) {
                            getToken(cb); //返回token
                        },function(token,cb) {
                            wxtoken[prefix] = {
                                token:token,
                                time:now+7000
                            };
                            // 文件保存
                            var client = redis.createClient(RDS_PORT,RDS_HOST,RDS_AUTH);
                            client.set(prefix +"access_token",'{"access_token":"'+token+'","expire_time":'+(+now+7000)+'}',redis.print);
                            client.quit();//必须关闭
                            cb(null, token);
                        },
                    ], function (err, result) {
                        getUserInfo(prefix, result,openid,cb);
                    });

                }else{
                    cb(null, Userinfo);
                }
            }
            catch (e) {
                cb('getToken error', e);
            }
        }
    });
}

module.exports = (function(option){
    RDS_PORT = option.redis.RDS_PORT;		//端口号
    RDS_HOST = option.redis.RDS_HOST;	//服务器IP
    RDS_AUTH= option.redis.RDS_AUTH;
    wx_config = option.wx;
    return {
        getToken:function(prefix){
            return function(cb){
                getAccessToken(prefix||"WxShop_", cb)
            }
        },
        getAccessToken:function(prefix){
            var q = Q.defer();
            var now = Math.floor(_.now()/1000);
            async.waterfall([function(cb) {
                getToken(prefix||"WxShop_",cb);
            }], function(error, result) {
                if (error) {
                    q.reject(error);
                }
                else {
                    wxtoken[prefix||"WxShop_"] = {
                        token:result,
                        time:now+7000
                    };
                    // 文件保存
                    var client = redis.createClient(RDS_PORT,RDS_HOST,RDS_AUTH);
                    client.set((prefix||"WxShop_") +"access_token",'{"access_token":"'+result+'","expire_time":'+(+now+7000)+'}',redis.print);
                    client.quit();//必须关闭
                    q.resolve(wxtoken);
                }
            });
            return q.promise;
        },
        getSignature:function(prefix){
            return function(prefix,url, cb) {
                getSignature( prefix||"WxShop_",url, cb);
            }
        },
        //获取关注用户基本信息（包括UnionID机制）
        getUserInfo:function(OpenID,prefix){
            var q = Q.defer();
            async.waterfall([
                function(callback){
                    getAccessToken(prefix||"WxShop_", callback); //获取TOKEN
                },
                function(result,callback){
                    getUserInfo(prefix||"WxShop_", result[prefix||"WxShop_"].token,OpenID,callback); //把缓存文件中的内容加载到 wxchace中
                }
            ], function (err, userinfo) {
                if(err){
                    q.reject(err);
                }else{
                    q.resolve(userinfo); //返回查询结果UserInfo
                }
            });
            return q.promise;
        },
        sendWxMessages:function(prefix,templateid,Data,touser,jumpurl){
            var q = Q.defer();
            async.waterfall([
                function(callback){
                    getAccessToken(prefix||"WxShop_",callback); //获取TOKEN
                },
                function(result,callback){
                    var url="https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+result[prefix].token;
                    var options = {
                        headers: {"Connection": "close"},
                        url: url,
                        method: 'POST',
                        json:true,
                        body: {data:Data,template_id : templateid,url : jumpurl,topcolor : "#FF0000",touser : touser}
                    };
                    request(options, function(error, response, body){
                        if (!error && response.statusCode == 200) {
                            callback(null, body)
                        }else{
                            callback(error)
                        }
                    });
                }
            ], function (err, result) {
                if(err){
                    q.reject(err);
                }else{
                    q.resolve(result); //返回查询结果UserInfo
                }
            });
            return q.promise;
        }
    }
})